package de.fuberlin.enginetesting;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import org.apache.commons.io.FileUtils;

import de.fuberlin.offloading.Engine;
import de.fuberlin.offloading.Algorithms.AlgName;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.util.Base64;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

//The app to test the engine
public class EngineTesting extends Activity {
	
	private static final int SELECT_FILE_CODE = 0;
	private static final String FILES_DIR_NAME = "enginetesting.files";

	private EditText param1;
	private String param3;
	private Engine offloadingEngine;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_layout);
		param1 = (EditText) findViewById(R.id.param1Entered);
		param3 = null;
        new File(Environment.getExternalStorageDirectory().getPath() + "/" + FILES_DIR_NAME).mkdir();
		offloadingEngine = new Engine(this.getApplicationContext());
	}
	
	@Override
	public void onPause() {
		super.onPause();
		offloadingEngine.savePersistentParams();
	}
	
	@Override
    public void onDestroy() {
        super.onDestroy();
        offloadingEngine.unregisterBroadcastReceivers();
    }

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_engine_testing, menu);
		return true;
	}
	
	public void onClickedGetMainView(View view) {
		setContentView(R.layout.main_layout);
		param1 = (EditText) findViewById(R.id.param1Entered);
	}

	public void onClickedEngineValues(View view) {
		setContentView(R.layout.engine_params);
		//Persistent parameters, without battery parameters, now only the CSRs remain (Computation Speed Relations)
		if (offloadingEngine.getCsrFromAlg(AlgName.doSomeLoops) == -1) ((TextView) findViewById(R.id.doSomeLoopsCsr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.doSomeLoopsCsr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.doSomeLoops)), 7)));
		if (offloadingEngine.getCsrFromAlg(AlgName.fileAndLoops) == -1) ((TextView) findViewById(R.id.fileAndLoopsCsr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.fileAndLoopsCsr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.fileAndLoops)), 7)));
		if (offloadingEngine.getCsrFromAlg(AlgName.doSomeLoops2) == -1) ((TextView) findViewById(R.id.doSomeLoops2Csr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.doSomeLoops2Csr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.doSomeLoops2)), 7)));
		if (offloadingEngine.getCsrFromAlg(AlgName.doublingOf) == -1) ((TextView) findViewById(R.id.doublingOfCsr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.doublingOfCsr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.doublingOf)), 7)));
		if (offloadingEngine.getCsrFromAlg(AlgName.fibonacciIterative) == -1) ((TextView) findViewById(R.id.fibonacciIterativeCsr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.fibonacciIterativeCsr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.fibonacciIterative)), 7)));
		if (offloadingEngine.getCsrFromAlg(AlgName.fibonacciRecursive) == -1) ((TextView) findViewById(R.id.fibonacciRecursiveCsr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.fibonacciRecursiveCsr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.fibonacciRecursive)), 7)));
		if (offloadingEngine.getCsrFromAlg(AlgName.randomArraySelectionSort) == -1) ((TextView) findViewById(R.id.sortArrayCsr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.sortArrayCsr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.randomArraySelectionSort)), 7)));
		if (offloadingEngine.getCsrFromAlg(AlgName.isPrime) == -1) ((TextView) findViewById(R.id.isPrimeCsr)).setText("NotCalc");
		else ((TextView) findViewById(R.id.isPrimeCsr)).setText(Double.toString(EngineTesting.round(((double) offloadingEngine.getCsrFromAlg(AlgName.isPrime)), 7)));
		//Non persistent parameters
		((TextView) findViewById(R.id.textView11)).setText(Double.toString(EngineTesting.round(offloadingEngine.getPing(), 7)));
		((TextView) findViewById(R.id.textView181)).setText(Double.toString(EngineTesting.round(offloadingEngine.getTransferredBytesMs(), 7)));
		if (offloadingEngine.isConnectionAvailable()) ((TextView) findViewById(R.id.textView14)).setText("Yes");
		else ((TextView) findViewById(R.id.textView14)).setText("No");
		if (offloadingEngine.isServerAvailable()) ((TextView) findViewById(R.id.textView16)).setText("Yes");
		else ((TextView) findViewById(R.id.textView16)).setText("No");
		((TextView) findViewById(R.id.textView18)).setText(offloadingEngine.getConnType());
	}
	
	private void setConcreteAlgValues (String result) {
		if (offloadingEngine.getEstAndroidRuntime() == -1) ((TextView) findViewById(R.id.textView30)).setText("NotCalc");
		else ((TextView) findViewById(R.id.textView30)).setText(Double.toString(EngineTesting.round(offloadingEngine.getEstAndroidRuntime(), 7)));
		if (offloadingEngine.getEstOffloadingTime() == -1) ((TextView) findViewById(R.id.textView4)).setText("NotCalc");
		else ((TextView) findViewById(R.id.textView4)).setText(Double.toString(EngineTesting.round(offloadingEngine.getEstOffloadingTime(), 7)));
		if (offloadingEngine.getEstServerRuntime() == -1) ((TextView) findViewById(R.id.textView42)).setText("NotCalc");
		else ((TextView) findViewById(R.id.textView42)).setText(Double.toString(EngineTesting.round(offloadingEngine.getEstServerRuntime(), 7)));
		if (offloadingEngine.getEstimsOverhead() == -1) ((TextView) findViewById(R.id.textView9997)).setText("NotCalc");
		else ((TextView) findViewById(R.id.textView9997)).setText(Double.toString(EngineTesting.round(offloadingEngine.getEstimsOverhead(), 7)));
		if (offloadingEngine.isOffloadingDone()) {
			((TextView) findViewById(R.id.textView29)).setText("Yes");
			((TextView) findViewById(R.id.textView13)).setText(R.string.ServerEstimatedTime);
		}
		else {
			((TextView) findViewById(R.id.textView29)).setText("No");
			((TextView) findViewById(R.id.textView13)).setText(R.string.AndroidEstimatedTime); 
		}
		((TextView) findViewById(R.id.textView14)).setText(Double.toString(EngineTesting.round(offloadingEngine.getOverallTime(), 7)));
		if (offloadingEngine.getRealServerTime() == -1) ((TextView) findViewById(R.id.textView16)).setText("None");
		else ((TextView) findViewById(R.id.textView16)).setText(Double.toString(EngineTesting.round(offloadingEngine.getRealServerTime(), 7)));
		((TextView) findViewById(R.id.textView18)).setText(result);
	}
	
	public void onClickedChooseFile(View view) {
		Intent pickFileIntent = new Intent("org.openintents.action.PICK_FILE");
		pickFileIntent.setData(Uri.parse("file://" + Environment.getExternalStorageDirectory().getPath() + "/" + FILES_DIR_NAME));
		pickFileIntent.putExtra("org.openintents.extra.TITLE", "Please select a file");
		try {
		    startActivityForResult(pickFileIntent, SELECT_FILE_CODE);
		} catch (ActivityNotFoundException e1) {
		    try {
		    	Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=org.openintents.filemanager"));
		        startActivity(marketIntent);
		    } catch (ActivityNotFoundException e2) {
		        Toast.makeText(this, "Market not installed.", Toast.LENGTH_SHORT).show();
		    }

		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
	        case SELECT_FILE_CODE:
	        if (resultCode == RESULT_OK) {
	            Uri uri = data.getData(); // Get the Uri of the selected file 
				try {
					param3 = EngineTesting.getPath(this.getApplicationContext(), uri); // Get the path
				} catch (URISyntaxException e) {
					//Shouldn't happen
					e.printStackTrace();
				}
	        }
	        break;
	    }
	    super.onActivityResult(requestCode, resultCode, data);
	}

	public void onClickedDoSomeLoops(View view) {
		String result = offloadingEngine.execute(AlgName.doSomeLoops, param1.getText().toString());
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.doSomeLoops);
		setConcreteAlgValues(result);
	}
	
	public void onClickedFileAndLoops(View view) {
		String fileContent = "";
		if (param3 != null) {
			try {
				byte[] fileBytes = FileUtils.readFileToByteArray(new File(param3));
				fileContent = Base64.encodeToString(fileBytes, Base64.DEFAULT);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		String result = offloadingEngine.execute(AlgName.fileAndLoops, param1.getText().toString(), fileContent);
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.fileAndLoops);
		setConcreteAlgValues(result);
	}
	
	public void onClickedDoSomeLoops2(View view) {
		String result = offloadingEngine.execute(AlgName.doSomeLoops2, param1.getText().toString());
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.doSomeLoops2);
		setConcreteAlgValues(result);
	}
	
	public void onClickedDoublingOf(View view) {
		String result = offloadingEngine.execute(AlgName.doublingOf, param1.getText().toString());
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.doublingOf);
		setConcreteAlgValues(result);
	}
	
	public void onClickedFibonacciRecursive(View view) {
		String result = offloadingEngine.execute(AlgName.fibonacciRecursive, param1.getText().toString());
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.FibonacciRecursive);
		setConcreteAlgValues(result);
	}
	
	public void onClickedFibonacciIterative(View view) {
		String result = offloadingEngine.execute(AlgName.fibonacciIterative, param1.getText().toString());
		if (result.length() >= 19) result = "Overflowed result";
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.FibonacciIterative);
		setConcreteAlgValues(result);
	}
	
	public void onClickedSortArray(View view) {
		String result = offloadingEngine.execute(AlgName.randomArraySelectionSort, param1.getText().toString());
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.SortArray);
		setConcreteAlgValues(result);
	}

	public void onClickedIsPrime(View view) {
		String result = offloadingEngine.execute(AlgName.isPrime, param1.getText().toString());
		setContentView(R.layout.exec_data);
		((TextView) findViewById(R.id.textView0)).setText(R.string.isPrime);
		setConcreteAlgValues(result);
	}
	
	private static double round(double nD, int nDec) {
	  return Math.round(nD*Math.pow(10,nDec))/Math.pow(10,nDec);
	}
	
	private static String getPath(Context context, Uri uri) throws URISyntaxException {
	    if ("content".equalsIgnoreCase(uri.getScheme())) {
	        String[] projection = { "_data" };
	        Cursor cursor = null;
	        try {
	            cursor = context.getContentResolver().query(uri, projection, null, null, null);
	            int column_index = cursor.getColumnIndexOrThrow("_data");
	            if (cursor.moveToFirst()) {
	                return cursor.getString(column_index);
	            }
	        } catch (Exception e) {
	            // Eat it
	        }
	    }
	    else if ("file".equalsIgnoreCase(uri.getScheme())) {
	        return uri.getPath();
	    }
	    return null;
	}
	
}
